//
//  UIViewController+Transitions.swift
//  HeadlineNews
//
//  Created by han on 2019/6/20.
//  Copyright © 2019 han. All rights reserved.
//

import UIKit

var transitedTypeKey = 101

extension UIViewController {
    // 当前VC的转场进入的动画
    var transitionType: TransitionType {
        set {
            objc_setAssociatedObject(self, &transitedTypeKey, newValue, objc_AssociationPolicy.OBJC_ASSOCIATION_RETAIN_NONATOMIC)
        }
        get {
            if let rs = objc_getAssociatedObject(self, &transitedTypeKey) as? TransitionType {
                return rs
            }
            return TransitionType.none
        }
    }
}
// 自定义手势返回时，如果遇到tabbar，tabbar会和popVC不同步
// TODO: tabbar手势返回时，与viewController不同步，需要自定义tabbar隐藏动画。可以上下隐藏。
// 由于navigation和tabbar问题。水平方向转场最好还是别用Push自定义转场了，可以采用present模拟Push自定义

// MARK: Push Pop转场
class NavigationDelegate: NSObject {
    private weak var navigationController: UINavigationController?
    private var animatedTransitioning = AnimatedTransitioning.init()
    private var popPanGesture: UIPanGestureRecognizer?
    private var popPanGestureEnable: Bool = false
    private let taskLock = NSLock()
    
    private var interactiveTransition: UIPercentDrivenInteractiveTransition? 
    
    // 系统返回监听不到
    private var isTransition: Bool = false
    
    override init() {
        super.init()
    }
    
    init(navigationController: UINavigationController) {
        super.init()
        self.navigationController = navigationController
        popPanGesture = UIPanGestureRecognizer(target: self, action: #selector(popPanGetstureHandler(recognizer:)))
        popPanGesture?.delegate = self
        popPanGesture?.isEnabled = false
        self.navigationController?.view.addGestureRecognizer(popPanGesture!)
        // 由于采用的是在navigation的view上添加手势，所以很容易造成，多次返回手势POP好几个页面，但是返回动画很慢。所以需要监听一下transition动画
        
    }

    func isPopGestureEnabled(isEnabled: Bool) {
        popPanGesture?.isEnabled = isEnabled
        popPanGestureEnable = isEnabled
    }
    
}

extension NavigationDelegate: UIGestureRecognizerDelegate {
    @objc func popPanGetstureHandler(recognizer: UIPanGestureRecognizer) {
       
        guard let view = recognizer.view else { return }
        
        let translation = recognizer.translation(in: view)
        var progress = translation.x/view.frame.width
        progress = min(1.0, max(0.0, abs(progress)))
        
        switch recognizer.state {
        case .began:
            let location = recognizer.location(in: view)
            let velocity = recognizer.velocity(in: view)
            
            guard let count = navigationController?.viewControllers.count else { return }
            
            // 监听transition动画。
            guard animatedTransitioning.isAnimation == false else { return }
            
            if location.x < view.bounds.midX  && velocity.x > 0 && count > 1 {
                self.interactiveTransition = UIPercentDrivenInteractiveTransition()
                self.navigationController?.popViewController(animated: true)
            }
        case .changed:
            self.interactiveTransition?.update(progress)
        case .ended, .cancelled: // 假如动画时间过长，多次执行手势，会多次返回。
            if progress < 0.5 || recognizer.state == .cancelled {
                self.interactiveTransition?.cancel()
            } else {
                self.interactiveTransition?.finish()
            }
            self.interactiveTransition = nil
        default: break
            
        }
 
    }
    
    func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldReceive touch: UITouch) -> Bool {
        return popPanGestureEnable
    }
}

// MARK: push pop 动画自定义
extension NavigationDelegate: UINavigationControllerDelegate {
    func navigationController(_ navigationController: UINavigationController, animationControllerFor operation: UINavigationController.Operation, from fromVC: UIViewController, to toVC: UIViewController) -> UIViewControllerAnimatedTransitioning? {
        switch operation {
        case .push:
            animatedTransitioning.pushOpertaion = .push
            guard case TransitionType.push(_) = toVC.transitionType else { return nil }
            animatedTransitioning.transitionType = toVC.transitionType
        case .pop:
            animatedTransitioning.pushOpertaion = .pop
            guard case TransitionType.push(_) = fromVC.transitionType else { return nil }
            animatedTransitioning.transitionType = fromVC.transitionType
        default : return nil
        }
        return animatedTransitioning
    }
    
    func navigationController(_ navigationController: UINavigationController, interactionControllerFor animationController: UIViewControllerAnimatedTransitioning) -> UIViewControllerInteractiveTransitioning? {
        guard let animatedTransitioning:AnimatedTransitioning  = animationController as? AnimatedTransitioning, case TransitionType.push(let pushType) = animatedTransitioning.transitionType, pushType == .scale || pushType == .fromRight else {
            self.popPanGesture?.isEnabled = false
            return nil
        }
        if popPanGestureEnable == false {
            return nil
        }
        self.popPanGesture?.isEnabled = true
        return interactiveTransition
    }
    
}

// MARK: Present Dismiss转场
class PresentDelegate: NSObject {
    private weak var currentViewController: UIViewController?
    private var dismissPanGesture: UIPanGestureRecognizer?
    private var interactiveTransition: UIPercentDrivenInteractiveTransition?
    private var animatedTransitioning = AnimatedTransitioning.init()
    
    override init() {
        super.init()
    }
    
    init(currentViewController: UIViewController) {
        super.init()
        
        self.currentViewController = currentViewController
        dismissPanGesture = UIPanGestureRecognizer(target: self, action: #selector(dismissPanGetstureHandler(recognizer:)))
        dismissPanGesture?.delegate = self
        dismissPanGesture?.isEnabled = false
        self.currentViewController?.view.addGestureRecognizer(dismissPanGesture!)
    }
    
    func isDismissGestureEnabled(isEnabled: Bool) {
        dismissPanGesture?.isEnabled = isEnabled
    }
}

extension PresentDelegate: UIGestureRecognizerDelegate {
    // MARK: 左右拖动的时候
    @objc func dismissPanGetstureHandler(recognizer: UIPanGestureRecognizer) {
        guard let currentViewController = currentViewController, let view = recognizer.view else { return }

        let translation = recognizer.translation(in: view)
        var progress = translation.x/view.frame.width
        progress = min(1.0, max(0.0, abs(progress)))
        switch recognizer.state {
        case .began:
            let location = recognizer.location(in: view)
            let velocity = recognizer.velocity(in: view)
            if location.x < view.bounds.midX  && velocity.x > 0 {
                self.interactiveTransition = UIPercentDrivenInteractiveTransition()
                currentViewController.dismiss(animated: true, completion: nil)
            }
        case .changed:
            self.interactiveTransition?.update(progress)
        case .ended, .cancelled:
            if progress < 0.4 || recognizer.state == .cancelled {
                self.interactiveTransition?.cancel()
            } else {
                self.interactiveTransition?.finish()
            }
            self.interactiveTransition = nil
        default: break
            
        }
    }
}

// MARK: present dismiss 动画自定义
extension PresentDelegate: UIViewControllerTransitioningDelegate {
    func animationController(forPresented presented: UIViewController, presenting: UIViewController, source: UIViewController) -> UIViewControllerAnimatedTransitioning? {
        // presented 被presented的VC，presenting 正在这个VC弹
        // 如果是在tabbar的子VC上present，那么这个获取到到presenting是TabBarVC
        guard case TransitionType.present(_) = presented.transitionType else { return nil }
        
        animatedTransitioning.presentOperation = .present
        animatedTransitioning.transitionType = presented.transitionType
        return animatedTransitioning
    }
    
    func animationController(forDismissed dismissed: UIViewController) -> UIViewControllerAnimatedTransitioning? {
        guard case TransitionType.present(_) = dismissed.transitionType else { return nil }
        
        animatedTransitioning.presentOperation = .dismiss
        animatedTransitioning.transitionType = dismissed.transitionType
        return animatedTransitioning
    }
    
    func interactionControllerForDismissal(using animator: UIViewControllerAnimatedTransitioning) -> UIViewControllerInteractiveTransitioning? {
        guard let animatedTransitioning:AnimatedTransitioning  = animator as? AnimatedTransitioning, case TransitionType.present(.scale) = animatedTransitioning.transitionType else {
            self.dismissPanGesture?.isEnabled = false
            return nil
        }
        
        self.dismissPanGesture?.isEnabled = true
        return interactiveTransition
    }
    
    func interactionControllerForPresentation(using animator: UIViewControllerAnimatedTransitioning) -> UIViewControllerInteractiveTransitioning? {
        return nil
    }
}


// Useage:

/**
 // present 转场
 let list =  NewsListViewController()
 list.transitionType = .present(.scale)
 list.presentDelegate?.isDismissGestureEnabled(isEnabled: true)
 self.present(list, animated: true, completion: nil)
 
 var presentDelegate : PresentDelegate?
 
 init() {
 super.init(nibName: nil, bundle: nil)
 initPresentDelegate()
 }
 
 required init?(coder aDecoder: NSCoder) {
 super.init(coder: aDecoder)
 initPresentDelegate()
 }
 
 func initPresentDelegate() {
 presentDelegate = PresentDelegate(currentViewController: self)
 self.transitioningDelegate = presentDelegate
 }
 
 // push 转场
 
 var navigationDelegate: NavigationDelegate?
 
 override func viewDidLoad() {
 super.viewDidLoad()
 // 用于自定义push转场动画
 self.navigationDelegate = NavigationDelegate(navigationController: self)
 self.navigationDelegate?.isPopGestureEnabled(isEnabled: true)
 self.delegate = self.navigationDelegate
 }
 
 // Tabbar 转场
 self.tabbarAnimation = AnimatedTransitioning()
 //        self.tabbarAnimation?.transitionType = .tab(.fromRight)
 self.tabbarAnimation?.transitionType = .none
 
 // 不同tabbar的子VC转场动画
 func tabBarController(_ tabBarController: UITabBarController, animationControllerForTransitionFrom fromVC: UIViewController, to toVC: UIViewController) -> UIViewControllerAnimatedTransitioning? {
 guard let transitionType = tabbarAnimation?.transitionType, case TransitionType.tab(_) = transitionType else { return nil }
 
 guard let fromIndex = tabBarController.viewControllers?.firstIndex(of: fromVC), let endIndex = tabBarController.viewControllers?.firstIndex(of: toVC) else { return nil }
 
 tabbarAnimation?.tabbarOpertaion = fromIndex < endIndex ?.leftToRight:.rightToLeft
 
 return tabbarAnimation
 }
 
 
 */

